/*
 * Copyright 2022-2029 heshuixing(https://gitee.com/heshuixing)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mercury.ec.framework.air.core.channel.service;

import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.mercury.ec.framework.air.core.client.AirClient;
import com.mercury.ec.framework.air.core.client.AirClientFactory;
import com.mercury.ec.framework.air.core.property.AirChannelProperties;
import com.mercury.ec.framework.common.enums.CommonStatusEnum;
import com.mercury.ec.framework.common.enums.ProductTypeEnum;
import com.mercury.ec.framework.common.util.object.BeanUtils;
import com.mercury.ec.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.mercury.ec.module.basic.dal.dataobject.channel.ChannelDO;
import com.mercury.ec.module.basic.dal.mysql.channel.ChannelMapper;
import com.mercury.ec.module.basic.mq.message.ChannelUpdateMessage;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import java.util.stream.Collectors;

import static com.mercury.ec.framework.common.util.cache.CacheUtils.buildCache;

/**
 * 机票渠道实现
 *
 * @author hesx
 */
@Slf4j
public class AirChannelServiceImpl implements AirChannelService {

    /**
     * {@link AirClient} 缓存，通过它异步刷新 airClientFactory
     */
    @Getter
    private final LoadingCache<Long, AirClient> idClientCache = buildCache(Duration.ofSeconds(10L),
            new CacheLoader<Long, AirClient>() {

                @Override
                public AirClient load(Long id) {
                    // 查询，然后尝试刷新
                    ChannelDO channel = channelMapper.selectById(id);
                    if (channel != null && CommonStatusEnum.isEnable(channel.getStatus())) {
                        AirChannelProperties properties = BeanUtils.toBean(channel, AirChannelProperties.class);
                        airClientFactory.createOrUpdateAirClient(properties);
                    }
                    return airClientFactory.getAirClient(id);
                }
            });


    @Resource
    private AirClientFactory airClientFactory;

    @Resource
    private ChannelMapper channelMapper;


    @Override
    public void clearAirClientCache(ChannelUpdateMessage channelUpdateMessage) {
        idClientCache.invalidate(channelUpdateMessage.getChannelId());
    }

    @Override
    public AirClient getAirClient(Long id) {
        return idClientCache.getUnchecked(id);
    }

    @Override
    public List<AirClient> getAirSearchClients() {
        List<ChannelDO> channelDOS = channelMapper.selectList(new LambdaQueryWrapperX<ChannelDO>()
                .eq(ChannelDO::getProductType, ProductTypeEnum.AIR.getType())
                .eq(ChannelDO::getStatus, CommonStatusEnum.ENABLE.getStatus())
                .eq(ChannelDO::getApplySearch, true));
        // 去除重复渠道设置
        channelDOS = channelDOS.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(p -> p.getChannelType() + p.getApiAccount()))),  ArrayList::new));
        List<AirClient> airClients = new ArrayList<>();
        channelDOS.forEach(p -> airClients.add(idClientCache.getUnchecked(p.getId())));
        return airClients;
    }

    @Override
    public List<AirClient> getAirBookClients() {
        List<ChannelDO> channelDOS = channelMapper.selectList(new LambdaQueryWrapperX<ChannelDO>()
                .eq(ChannelDO::getProductType, ProductTypeEnum.AIR.getType())
                .eq(ChannelDO::getStatus, CommonStatusEnum.ENABLE.getStatus())
                .eq(ChannelDO::getApplyBook, true));
        // 去除重复渠道设置
        channelDOS = channelDOS.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(p -> p.getChannelType() + p.getApiAccount()))),  ArrayList::new));
        List<AirClient> airClients = new ArrayList<>();
        channelDOS.forEach(p -> airClients.add(idClientCache.getUnchecked(p.getId())));
        return airClients;
    }
}
